package streamdef;

import java.util.HashMap;
import java.util.Vector;

public class StreamDefinitionManager {
	private static StreamDefinitionManager sInstance = null;

	public static StreamDefinitionManager instance() {
		if (sInstance == null)
			sInstance = new StreamDefinitionManager();

		return sInstance;
	}

	// streamID -> MainQuery-instance
	private HashMap<Long, StreamCondition> queries = null;
	private Vector<Long> streamIDs = null;
	private Vector<Long> streamIDsUsedInOtherQueries = null;
	private Vector<Long> streamIDsUsedInOtherQueriesButMayNotAlwaysOccur = null;

	private StreamDefinitionManager() {
		init();
	}

	public void reset() {
		if (queries != null)
			queries.clear();
		if (streamIDs != null)
			streamIDs.clear();
		if (streamIDsUsedInOtherQueries != null)
			streamIDsUsedInOtherQueries.clear();
		if (streamIDsUsedInOtherQueriesButMayNotAlwaysOccur != null)
			streamIDsUsedInOtherQueriesButMayNotAlwaysOccur.clear();
	}

	protected void finalize() {
		reset();
	}

	public void init() {
		reset();
		queries = new HashMap<Long, StreamCondition>();
		streamIDs = new Vector<Long>();
		streamIDsUsedInOtherQueries = new Vector<Long>();
		streamIDsUsedInOtherQueriesButMayNotAlwaysOccur = new Vector<Long>();
	}

	public void addParsedQuery(StreamCondition query) {
		if (query != null) {
			queries.put(new Long(query.getStreamID()), query);
			streamIDs.add(new Long(query.getStreamID()));

			Vector<Long> usedExternalIDs = query.getUsedExternalStreamIDs();
			for (int i = 0; i < usedExternalIDs.size(); ++i) {
				long usedExtID = usedExternalIDs.get(i);
				if (!streamIDsUsedInOtherQueries.contains(usedExtID))
					streamIDsUsedInOtherQueries.add(new Long(usedExtID));

				Vector<Long> internalIDs = query
						.getInternalStreamIDsForExternalStreamID(usedExtID);
				boolean mayNotAlwaysOccur = false;
				for (int j = 0; j < internalIDs.size() && !mayNotAlwaysOccur; ++j) {
					if (!query.mayOccur(internalIDs.get(j)))
						mayNotAlwaysOccur = true;
				}
				if (mayNotAlwaysOccur)
					streamIDsUsedInOtherQueriesButMayNotAlwaysOccur
							.add(new Long(usedExtID));
			}
		}
	}

	public StreamCondition getParsedQuery(long ID) {
		return queries.get(ID);
	}

	public Vector<Long> getStreamIDs() {
		return streamIDs;
	}

	public boolean streamIDIsUsedInOtherQueries(long ID) {
		return streamIDsUsedInOtherQueries.contains(ID);
	}

	public boolean streamIDIsUsedInOtherQueriesButMayNotAlwaysOccur(long ID) {
		return streamIDsUsedInOtherQueriesButMayNotAlwaysOccur.contains(ID);
	}
}
